import type {
  BaseStyleConfig,
  ComponentType,
  IInstance,
  IPersonalizationItem,
  IPersonalizationItemConfig,
  IRenderFragment,
  MountTarget,
  PersonalizationStorageType,
  PlatformTypeValue,
  ResetType,
  SettingsStyleIdType,
  StorageKeys,
  StorageMapKeys,
  StorageMapValues,
  StyleConfigKey,
} from '../../../types/interfaces'
import type { PageType } from '../../page_handler/type'
import { withRefreshLoader } from '../../../components/refresh_loader'
import {
  getValidSymbol,
  HOSTNAME,
  ITEM_STATE,
  logger,
  MessageType,
  PERSONALIZATION_STORAGE_CONFIG,
  PlatformConfigs,
  PROJECT_PREFIX,
  RESET_TYPES,
  SettingsStyleId,
  VALID_RESULT,
} from '../../../types/constants'
import {
  FILE_UPLOAD_MODE,
  MESSAGE_STYLES,
  StyleInjectPosition,
  SYMBOLS,
} from '../../../types/interfaces'
import { createStandardStyleTag } from '../../style_injector'
import { ToolKit } from '../../utils/toolkit'
import { PageStorage } from '../storage/page_storage'

/**
 * 个性化设置项基类（抽象类）
 */
export abstract class UserPref extends PageStorage implements IPersonalizationItem {
  /**
   * 公共属性
   */
  componentType: 'collection' | 'single' = 'collection'

  declare readonly config: IPersonalizationItemConfig
  initFailed = false
  invalidMessages: Map<string, string> = new Map()
  // 模式是否生效
  modeIsUsed = false
  /**
   * 实例存储
   */
  protected instances: Map<string, IInstance> = new Map()
  protected cachedValues: Map<string, string> = new Map()
  protected originalValues: Map<string, string> = new Map()
  protected cachedModes: Map<string, string> = new Map()
  protected lastModes: Map<string, string> = new Map()
  protected cachedExtended: Map<string, Map<string, unknown>> = new Map() // 用于子类扩展存储
  protected defaultMode = 'text'
  protected debouncedSaves: Map<string, (() => void) & {
    flush: () => void
  }> = new Map()

  /**
   * 静态实例（多例模式）
   */
  private static _instances = new Map<string, UserPref>()

  /**
   * 抽象属性（子类必须实现）
   */
  // ID
  abstract readonly id: string
  // 样式名称
  abstract readonly name: PersonalizationStorageType
  // 样式配置键
  abstract readonly styleConfigKey: StyleConfigKey
  // CSS属性和值后缀
  abstract readonly cssProperty: string
  abstract readonly cssValueSuffix: string
  // 是否启用空的样式元素
  protected readonly enableEmptyStyleElement: boolean = true
  // 防抖保存时间（单位毫秒）
  readonly debouncedSaveTimeout: number = 500
  // 页面类型
  protected pageType: PageType = this.getPageType(true) || 'default'
  // 支持的平台
  readonly supportedPlatforms: PlatformTypeValue[] | '*' = '*'
  // 不支持的平台
  readonly notSupportedPlatforms: PlatformTypeValue[] | undefined = undefined
  // 支持的页面类型
  readonly supportedPages: Partial<Record<PlatformTypeValue, PageType[]>> | '*' = '*'
  // 不支持的页面类型
  readonly notSupportedPages: Partial<Record<PlatformTypeValue, PageType[]>> | undefined

  // 抽象函数（子类必须实现）
  abstract createComponent(config: BaseStyleConfig, value: string, mode: string, debouncedSave: (() => void) & { flush: () => void }): ComponentType
  abstract handleCheck(value: string, mode?: string): { status: ValidResultType, error: string }

  // 计算属性（当前键有顺序要求，第一个为值，第二个为模式，第三个为扩展...）
  get storageKeys(): StorageKeys<this['name']>[] {
    const defaultKeys = ['value']
    const keys = PERSONALIZATION_STORAGE_CONFIG[this.name]

    if (!keys)
      return defaultKeys

    return keys || []
  }

  get styleId(): string {
    const styleId = SettingsStyleId[this.name as SettingsStyleIdType]
    if (!styleId) {
      logger.warn(`未找到样式 ID: ${this.name}`)
      return `${PROJECT_PREFIX}-${this.name.toLowerCase()}-style` // 提供默认值
    }
    return styleId
  }

  protected constructor(config: IPersonalizationItemConfig) {
    super()
    this.config = config
  }

  description?: string | undefined

  /**
   * 模块是否启用
   */
  isEnableModule(): boolean {
    const configs = this.getStyleConfigs()
    const isEmptyConfig = !configs.global.length && !configs.framework.length

    return (this.supportedPlatforms === '*' || this.supportedPlatforms.includes(HOSTNAME))
      && (!this.notSupportedPlatforms || !this.notSupportedPlatforms.includes(HOSTNAME))
      && ((this.supportedPages === '*' || (this.supportedPages[HOSTNAME] || []).includes(this.pageType))
        && (!this.notSupportedPages || !this.notSupportedPages[HOSTNAME]?.includes(this.pageType))) && !isEmptyConfig
  }

  /**
   * 显式初始化方法（由子类在属性初始化后调用）
   */
  protected initialize(): void {
    this.isInitialized = false
    this.init()
    this.isInitialized = true
  }

  /**
   * 获取单例实例
   */
  static getInstance<T extends UserPref>(
    this: new (config: IPersonalizationItemConfig) => T,
    config: IPersonalizationItemConfig,
  ): T {
    const className = this.name // 获取子类名
    if (!UserPref._instances.has(className)) {
      // 创建子类实例并存储
      UserPref._instances.set(className, new this(config))
    }
    return UserPref._instances.get(className) as T
  }

  /**
   * 初始化方法
   */
  private init(): void {
    // 清空所有缓存
    this.clearAllCaches()

    const { global: globalConfigs, framework: frameworkConfigs } = this.getStyleConfigs()

    // 处理全局配置
    globalConfigs.forEach(config => this.processConfig(config))

    // 处理框架配置
    frameworkConfigs.forEach(config => this.processConfig(config))

    // 重置保存与更新状态
    this.getInstanceIds().forEach((id) => {
      this.setStatusValue(id, false, false)
    })

    this.initAfter()
  }

  /**
   * 初始化后
   */
  protected initAfter(): void {}

  /**
   * 清空所有缓存
   */
  private clearAllCaches(): void {
    this.cachedValues.clear()
    this.originalValues.clear()
    this.cachedModes.clear()
    this.lastModes.clear()
    this.invalidMessages.clear()
    this.instances.clear()
    this.cachedExtended.clear()
    this.debouncedSaves.clear()
  }

  /**
   * 处理单个配置项
   * @param config 样式配置
   */
  private processConfig(config: BaseStyleConfig | undefined): void {
    if (!config) {
      logger.warn(`[${this.name}] 配置信息为空，跳过此配置`)
      return
    }

    if (!config.styleVar) {
      logger.warn(`[${this.name}] ${config.id} 未找到样式变量'styleVar'，跳过此配置`)
      return
    }

    const id = this.generateId(config.styleVar)
    const { value, mode } = this.getStorageValues(id)

    // 为每个选择器创建独立的防抖函数
    const debouncedSave = ToolKit.func.enhanceDebounce(() => this.saveChanges(id), this.debouncedSaveTimeout)
    this.debouncedSaves.set(id, debouncedSave)

    // 创建组件实例
    const component = this.createComponent(config, value, mode, debouncedSave)

    // 存储组件实例（带分类标识）
    if (this.checkInstanceIDDuplicated(id))
      logger.warn(`[${this.name}] 实例 ID 重复: ${id}`)

    this.instances.set(id, {
      id,
      instance: component,
      config,
    })
  }

  /**
   * 检查实例 ID 是否重复
   * @param id 实例ID
   */
  checkInstanceIDDuplicated(id: string): boolean {
    return this.instances.has(id)
  }

  /**
   * 获取所有实例
   */
  getInstances(): Map<string, IInstance> {
    return this.instances
  }

  /**
   * 获取所有实例ID
   */
  getInstanceIds(): string[] {
    return Array.from(this.instances.keys())
  }

  /**
   * 获取选择器
   */
  getSelector(id: string): { main: string, message: string } {
    return {
      main: this.componentType === 'collection'
        ? `.${this.config.className} .setting-item.render-${id}`
        : `.${this.config.className} .setting-item.render-${this.id}`,
      message: this.componentType === 'collection'
        ? `.${this.config.className} .${this.config.messageName}.${id}`
        : `.${this.config.className} .${this.config.messageName}.${this.id}`,
    }
  }

  /**
   * 获取当前平台的所有配置
   */
  private getStyleConfigs(): { global: BaseStyleConfig[], framework: BaseStyleConfig[] } {
    const platformConfig = PlatformConfigs[HOSTNAME]
    const configs: { global: BaseStyleConfig[], framework: BaseStyleConfig[] } = { global: [], framework: [] }

    if (!platformConfig)
      return configs

    // 从全局配置中获取
    const global_configs = platformConfig.global?.defaults
    if (global_configs && this.styleConfigKey in global_configs) {
      Object.entries(global_configs).forEach((item: any) => {
        const key = item[0]
        const config = item[1]
        if (key === this.styleConfigKey) {
          configs.global.push(...[config])
        }
      })
    }

    // 从框架配置获取
    Object.values(platformConfig.contents.framework).forEach((areaConfig: any) => {
      if (areaConfig[this.styleConfigKey]) {
        const items = Array.isArray(areaConfig[this.styleConfigKey])
          ? areaConfig[this.styleConfigKey]
          : [areaConfig[this.styleConfigKey]]
        configs.framework.push(...items)
      }
    })

    return configs
  }

  /**
   * 生成 ID
   */
  protected generateId(elementId: string): string {
    return this.componentType === 'collection' ? `${this.id}` : `${this.id}-${elementId}`.replace('--', '').toLowerCase()
  }

  render(): IRenderFragment[] {
    this.initialize()
    this.updateReferences()

    return Array.from(this.instances.values()).map(item => ({
      id: this.componentType === 'collection' ? item.id : this.id,
      type: this.id,
      html: item.instance.render(),
      // 分类
      category: item.config.categoryKey === 'id' ? item.config.id : item.config.category || item.config.id,
      // 排序优先级，越小越靠前
      priority: item.config.priority,
      remark: item.config.remark,
    }))
  }

  /**
   * 获取存储键前缀
   * @param id 元素ID
   */
  getStateStorageKeyPrefix(id: string) {
    return `${id}@`
  }

  /**
   * 获取存储键
   * @param id 元素ID
   * @param extendedKey 子类可选的扩展键名
   */
  private getStorageKeys(id: string, extendedKey?: string) {
    const keys: StorageMapKeys = {
      value: `${this.getStateStorageKeyPrefix(id)}${this.storageKeys[0]}`,
      mode: this.modeIsUsed ? `${this.getStateStorageKeyPrefix(id)}${this.storageKeys[1]}` : `${this.getStateStorageKeyPrefix(id)}${this.id}-mode`,
      changed: `${this.getStateStorageKeyPrefix(id)}${ITEM_STATE.CHANGED.suffix}`,
      saved: `${this.getStateStorageKeyPrefix(id)}${ITEM_STATE.SAVED.suffix}`,
    }

    // 允许子类扩展存储键
    if (extendedKey && this.storageKeys[2]) {
      keys[extendedKey] = `${this.storageKeys[2]}-${id}`
    }

    return keys
  }

  /**
   * 获取存储值
   * @param id 元素ID
   */
  getStorageValues(id: string): StorageMapValues {
    const storageKeys = this.getStorageKeys(id)
    return {
      value: this.storageGet(storageKeys.value, '') as string,
      mode: this.storageGet(storageKeys.mode, this.defaultMode) as string,
      changed: this.storageGet(storageKeys.changed, false),
      saved: this.storageGet(storageKeys.saved, false),
    }
  }

  /**
   * 更新存储值
   * @param id 元素ID
   * @param notEmpty 是否非空
   * @param changed 是否已更改
   * @param extended 子类可选的扩展数据 {key: value}
   */
  protected setStorageValues(id: string, notEmpty: boolean, changed: boolean, extended?: Record<string, unknown>): void {
    const storageKeys = this.getStorageKeys(id, extended && Object.keys(extended)[0])
    const value = this.cachedValues.get(id) || ''
    const mode = this.cachedModes.get(id) || this.defaultMode

    this.storageSet(storageKeys.value, value)
    this.storageSet(storageKeys.mode, mode)
    this.setStatusValue(id, notEmpty, changed, extended)

    // 处理子类扩展的存储
    if (extended) {
      const [key, value] = Object.entries(extended)[0]
      this.storageSet(storageKeys[key], value)

      // 更新缓存
      if (!this.cachedExtended.has(id)) {
        this.cachedExtended.set(id, new Map())
      }
      this.cachedExtended.get(id)?.set(key, value)
    }

    this.afterSetStorageValues(value)
  }

  /**
   * 更新状态值
   * @param id 元素ID
   * @param notEmpty 是否非空
   * @param changed 是否已更改
   * @param extended 子类可选的扩展数据 {key: value}
   */
  protected setStatusValue(id: string, notEmpty: boolean, changed: boolean, extended?: Record<string, unknown>): void {
    const storageKeys = this.getStorageKeys(id, extended && Object.keys(extended)[0])

    this.storageSet(storageKeys.changed, changed) // 标记更新状态
    this.storageSet(storageKeys.saved, notEmpty) // 标记保存状态
  }

  protected afterSetStorageValues(_value: string): void {}

  /**
   * 构建存储结果描述
   */
  createSaveResultDesc(value: string, limit: number = 100): string {
    return value.length > limit
      ? `存储结果（前${limit}个字符）: ${ToolKit.string.truncate(value, limit)}`
      : `存储结果: ${value}`
  }

  /**
   * 保存更改并更新UI
   * @param id 元素ID
   */
  protected saveChanges(id: string): void {
    this.updateMessage(id, true)
    const validType = this.check(id)

    if (validType === VALID_RESULT.VALID.value) {
      const cachedValue = this.cachedValues.get(id) as string || ''
      const originalValue = this.originalValues.get(id) as string || ''

      const notEmpty = cachedValue && cachedValue.length > 0
      const changed = this.isChanged(cachedValue, originalValue)

      this.handleStorageSave(id, notEmpty as boolean, changed as boolean)

      if (changed) {
        const { value, mode } = this.getStorageValues(id)

        if (this.modeIsUsed) {
          const desc = mode === FILE_UPLOAD_MODE.URL ? 'URL' : '普通'
          logger.info(`[${this.name}] 当前模式: ${mode}，校验结果: ${getValidSymbol(validType)} ${desc}${this.createSaveResultDesc(value)}`)
        }
        else {
          logger.info(`[${this.name}] 校验结果: ${getValidSymbol(validType)} ${this.createSaveResultDesc(value)}`)
        }
      }
    }
    else if (this.modeIsUsed) {
      // 如果没有通过校验，恢复到上一次模式
      this.cachedModes.set(id, this.lastModes.get(id) as string)
    }

    this.updateUiState(id, validType)
  }

  /**
   * 检查值是否已更改
   * @param newValue 新值
   * @param oldValue 旧值
   * @returns 是否已更改
   */
  protected isChanged(newValue: string, oldValue: string): boolean {
    return newValue !== oldValue
  }

  /**
   * 处理存储保存
   * @param id 元素ID
   * @param notEmpty 是否非空
   * @param changed 是否已更改
   */
  protected handleStorageSave(id: string, notEmpty: boolean, changed: boolean): void {
    this.setStorageValues(id, notEmpty, changed)
  }

  /**
   * 更新 UI 状态
   * @param id 元素ID
   * @param type 校验结果类型
   */
  updateUiState(id: string, type: ValidResultType): void {
    const { changed, saved } = this.getStorageValues(id)
    const cachedValue = this.cachedValues.get(id) as string || ''

    // 应用样式
    // 1）校验通过且有更改：显示更改状态
    // 2）没有保存：去掉保存状态
    // 3）校验不通过：显示无效状态
    const $container = $(this.getSelector(id).main)
    const addChangeClass = type === VALID_RESULT.VALID.value && changed
    const saveClass = !(saved && cachedValue) ? ITEM_STATE.SAVED.className : ''
    const removeSaveClass = saveClass.length > 0
    const addInvalidClass = type === VALID_RESULT.INVALID.value

    $container
      .toggleClass(ITEM_STATE.CHANGED.className, addChangeClass)
      .removeClass(saveClass)
      .toggleClass(ITEM_STATE.INVALID.className, addInvalidClass)

    const changeSymbol = addChangeClass ? ITEM_STATE.CHANGED.symbol : SYMBOLS.COLOR_CIRCLES.WHITE
    const saveSymbol = removeSaveClass ? ITEM_STATE.SAVED.symbol : SYMBOLS.COLOR_CIRCLES.WHITE
    const invalidSymbol = addInvalidClass ? ITEM_STATE.INVALID.symbol : SYMBOLS.COLOR_CIRCLES.WHITE

    logger.info(`[${this.name}] 状态更新：更改${changeSymbol} 去掉保存${saveSymbol} 无效${invalidSymbol}`)
  }

  /**
   * 应用样式到指定选择器
   */
  protected applyStyles(): void {
    try {
      // 收集所有需要应用的样式
      const styleRules: string[] = []
      const preProcessSelectors: string[] = []

      this.instances.forEach(({ id, config }) => {
        const { value } = this.getStorageValues(id)
        if (value && this.check(id) === VALID_RESULT.VALID.value) {
          const selector = this.resolveSelector(config)

          if (!selector)
            return

          // 收集需要预处理的元素
          if (this.needPreprocessElements()) {
            preProcessSelectors.push(selector)
          }

          // 生成样式规则
          styleRules.push(this.generateStyleRule(selector, value))
        }
      })

      // 应用预处理
      if (preProcessSelectors.length > 0) {
        this.preprocessElements(preProcessSelectors)
      }

      const styles = styleRules.join('\n')

      if (!styles && styles.length === 0 && !this.enableEmptyStyleElement)
        return

      // 如果没有任何样式规则，也需要创建一个空的样式元素，因为有重置使用场景
      // 最后应用，避免 CSS 层叠规则导致被覆盖
      createStandardStyleTag(this.styleId, styleRules.join('\n'), { allowEmpty: true, position: StyleInjectPosition.Last })
    }
    catch (error: any) {
      logger.error(`[${this.name}] 应用样式失败:`, error)
    }
  }

  /**
   * 解析选择器（可被子类覆盖）
   */
  protected resolveSelector(config: BaseStyleConfig): string | null {
    return typeof config.selector === 'function'
      ? config.selector()
      : config.selector
  }

  /**
   * 生成样式规则（可被子类覆盖）
   */
  protected generateStyleRule(selector: string, value: string): string {
    return `${selector} { ${this.cssProperty}: ${value}${this.cssValueSuffix} !important; }`
  }

  /**
   * 是否需要元素预处理（可被子类覆盖）
   */
  protected needPreprocessElements(): boolean {
    return false
  }

  /**
   * 元素预处理方法（可被子类覆盖）
   */
  protected preprocessElements(_selectors: string[]): void {
    // 默认不进行预处理
  }

  /**
   * 应用设置
   */
  apply(): void {
    this.applyStyles()
  }

  /**
   * 检查URL是否合法
   * @param id 元素ID
   * @param show 是否显示错误信息
   */
  check(id: string, show: boolean = false): ValidResultType {
    const cachedValue = this.cachedValues.get(id) as string || ''
    const cachedMode = this.cachedModes.get(id) as string || ''

    const valueValidData = this.handleCheck(cachedValue, cachedMode)

    // 如果为跳过状态，直接返回
    if (valueValidData.status === VALID_RESULT.SKIP.value)
      return valueValidData.status

    this.invalidMessages.set(id, valueValidData.error.length > 0 ? valueValidData.error : '')

    // 更新 UI 状态
    const $target = $(this.getSelector(id).main)

    if (!$target.length) {
      this.invalidMessages.set(id, `找不到目标元素: ${this.getSelector(id).main}`)
    }

    $target.toggleClass(ITEM_STATE.INVALID.className, valueValidData.status === VALID_RESULT.INVALID.value)

    if (valueValidData.status === VALID_RESULT.INVALID.value) {
      if (show && this.invalidMessages.get(id) as string) {
        this.updateMessage(id, false)
      }
    }

    return valueValidData.status
  }

  /**
   * 构建存储结果描述
   */
  createMessageDesc(message: string, data: string, limit: number = 500): string {
    let dataDesc = ''
    if (data.length > 0) {
      if (data.length > limit) {
        dataDesc = `当前数据的前${limit}个字符：${ToolKit.string.truncate(data, limit)}`
      }
      else {
        dataDesc = `当前数据：${data}`
      }
    }
    return message ? `${message}${dataDesc ? '，' : ''}${dataDesc}` : ''
  }

  /**
   * 处理消息
   * @param id 元素ID
   * @param message 消息内容
   * @param reset 是否重置消息
   * @param type 消息类型
   */
  handleMessage(id: string, message: string, reset: boolean = false, type: MessageType = MessageType.ERROR): boolean {
    const styleConfig = MESSAGE_STYLES[type]
    const $message = $(this.getSelector(id).message)

    if (!$message.length) {
      logger.warn(`[${this.name}] 找不到消息元素: ${this.getSelector(id).message}`)
      return false
    }

    if (reset) {
      $message
        .removeClass(Object.values(MESSAGE_STYLES).map(s => s.className).join(' '))
        .css({
          padding: 0,
          marginBottom: 0,
          width: 0,
          height: 0,
        })
      ToolKit.dom.setElementCssAttribute($message)
    }
    else {
      $message
        .text(message)
        .removeClass(Object.values(MESSAGE_STYLES).map(s => s.className).join(' '))
        .addClass(styleConfig.className)
        .css({
          width: '',
          height: '',
        })

      ToolKit.dom.setElementCssText($message, `
        display: block !important;
        padding: 10px !important;
        margin-bottom: 5px !important;
      `)
    }
    return true
  }

  /**
   * 更新消息
   * @param id 元素ID
   * @param reset 是否重置消息
   */
  updateMessage(id: string, reset: boolean = false): void {
    const cachedValue = this.cachedValues.get(id) as string || ''
    const cachedMode = this.cachedModes.get(id) as string || this.defaultMode
    const invalidMessage = this.invalidMessages.get(id) as string || ''

    const modeDesc = cachedMode === FILE_UPLOAD_MODE.URL ? 'URL模式' : '普通模式'
    const finalMessage = this.modeIsUsed ? `【${modeDesc}】${invalidMessage}` : invalidMessage

    const message = this.createMessageDesc(finalMessage, cachedValue)
    const status = this.handleMessage(id, message, reset)

    if (!status) {
      return
    }

    if (invalidMessage.length > 0)
      logger.warn(`[${this.name}] 更新消息: ${invalidMessage}`)
  }

  mount(target: MountTarget): void {
    // 处理 JQuery 类型
    if (target instanceof $) {
      this.instances.forEach(({ instance }) => {
        if (!instance)
          return
        instance.mount(target as JQuery<HTMLElement>)
      })
      return
    }

    // 处理 IBindableElement 数组类型
    if (Array.isArray(target)) {
      target.forEach(({ id, element }) => {
        const instance = this.instances.get(id)?.instance
        if (!instance)
          return

        // 为每个元素绑定独立的事件处理器
        instance.mount(element)
      })
    }
  }

  onInit(): void {
    this.onSave()
    this.afterInit()
  }

  private updateReferences(): void {
    this.getInstanceIds().forEach((id) => {
      const { value, mode } = this.getStorageValues(id)

      this.cachedValues.set(id, value)
      this.originalValues.set(id, value)
      this.cachedModes.set(id, mode)
      this.lastModes.set(id, mode)
    })
  }

  protected afterInit(): void {}
  protected handleBeforeSave(): void {}

  onSave(): void {
    this.handleBeforeSave()

    // 获取所有实例ID
    const instanceIds = this.getInstanceIds()

    // 检查所有实例的有效性
    const allValid = instanceIds.every((id) => {
      const result = this.check(id, true)
      if (result === VALID_RESULT.INVALID.value) {
        logger.warn(`[${this.name}] 实例 ${id} 验证失败，取消保存`)
        return false
      }
      return true
    })

    // 只有全部验证通过才执行应用
    if (allValid) {
      logger.important(`[${this.name}] 所有设置项验证通过，开始应用`)
      this.apply()
    }
    else {
      logger.warn(`[${this.name}] 存在验证失败的设置项，已取消保存操作`)
    }
  }

  /**
   * 重置样式
   * @param id 实例 ID
   */
  resetStyle(id: string): void {
    // 重置状态
    this.cachedValues.set(id, '')
    this.originalValues.set(id, '')
    this.cachedModes.set(id, this.defaultMode)
    this.lastModes.set(id, '')
    this.invalidMessages.set(id, '')
    // 应用重置
    this.apply()
  }

  /**
   * 重置组件
   * @param id 实例 ID
   */
  resetInput(id: string): void {
    // 重置组件
    this.instances.get(id)?.instance?.reset()
  }

  /**
   * 重置
   * @param type 重置类型
   */
  onReset(type: ResetType): void {
    this.getInstanceIds().forEach((id) => {
      if (type === RESET_TYPES.STYLE) {
        this.beforeResetStyle()
        this.resetStyle(id)
        this.afterResetStyle()
        withRefreshLoader()
      }
      else {
        this.beforeResetInput()
        this.resetInput(id)
        this.afterResetInput()
      }
    })
    this.afterReset()
  }

  protected afterReset(): void {}
  protected beforeResetStyle(): void {}
  protected afterResetStyle(): void {}
  protected beforeResetInput(): void {}
  protected afterResetInput(): void {}
}
